import random
import re

from django.core.cache import cache
from django.contrib.auth.models import Group
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework.exceptions import PermissionDenied, AuthenticationFailed  # DRF 默认会将异常消息放在 detail 字段
from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from django.core.validators import RegexValidator
from django.contrib.auth.models import Group, Permission
from django.contrib.auth import authenticate
from rest_framework.exceptions import ValidationError

# ✅ 正确方式：动态获取用户模型类
User = get_user_model()


class CustomTokenSerializer(TokenObtainPairSerializer):
    """自定义登录响应数据"""

    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        # 添加自定义声明
        token['username'] = user.username
        return token

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')

        # 尝试验证用户
        user = authenticate(request=self.context['request'], username=username, password=password)
        if not user:
            raise ValidationError({'detail': '用户名或密码错误', "status_origin": 210})

        # 检查用户是否激活
        if not user.is_active:
            raise ValidationError({'detail': '用户未激活', "status_origin": 210})

        # 检查用户是否内部员工
        if not user.is_staff:
            raise ValidationError({'detail': '不是合法用户', "status_origin": 210})

        # 检查是否可以访问后端接口
        if not user.has_perm('jewelry.access_account_page'):
            raise ValidationError({"detail": "您没有访问权限", "status_origin": 210})

        # 如果验证通过，返回数据
        data = super().validate(attrs)
        data.update({
            'userid': user.id,
            'username': user.username,
            'permissions': list(user.get_all_permissions()),
            'roles': list(user.groups.values_list('name', flat=True)),
            'is_superuser': user.is_superuser,
        })
        return data


# ############## 用户管理序列化器:
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['is_superuser'] = user.is_superuser
        return token


class UserSerializer(serializers.ModelSerializer):
    username = serializers.CharField(
        max_length=150,
        validators=[
            UniqueValidator(
                queryset=User.objects.all(),
                message="用户名已被使用",
            )
        ],
        required=True,
        error_messages={
            'blank': '用户名不能为空',  # 处理空值
            'required': '请提供用户名'  # 处理字段缺失
        }
    )

    phone = serializers.CharField(
        max_length=20,
        validators=[
            RegexValidator(
                r'^1[3-9]\d{9}$',
                message="手机号格式不正确"
            ),
            UniqueValidator(
                queryset=User.objects.all(),
                message="手机号已被其他用户使用",
            )
        ],
        required=True,
        error_messages={
            'blank': '手机号不能为空',  # 当required=True时有效
            'invalid': '请输入有效的手机号'
        }

    )

    email = serializers.EmailField(
        validators=[
            UniqueValidator(
                queryset=User.objects.all(),
                message="邮箱已被使用",
            )
        ],
        required=True,
        error_messages={
            'blank': '邮箱不能为空',
            'required': '请提供邮箱地址',
            'invalid': '邮箱格式不正确'  # 额外添加格式错误
        }
    )

    # 接收 Group 的主键列表（适用于多对多）
    groups = serializers.PrimaryKeyRelatedField(
        queryset=Group.objects.all(),
        many=True,  # 多对多关系设为 True
        required=False
    )

    class Meta:
        model = User
        fields = ['id', 'username', 'phone', 'email', 'is_staff', 'is_active', 'groups', 'password']
        extra_kwargs = {
            'password': {
                'write_only': True,
                'required': True,
                'error_messages': {
                    'blank': '密码不能为空',
                    'required': '请设置登录密码'
                }
            }
        }

    def create(self, validated_data):
        # 提取密码和组信息
        password = validated_data.pop('password', None)
        groups_data = validated_data.pop('groups', [])
        # 创建用户，此时不处理组
        user = User.objects.create_user(**validated_data)
        # 设置密码
        user.set_password(password)
        # 保存用户
        user.save()
        # 关联组
        user.groups.set(groups_data)
        return user

    # def validate_password(self, value):
    #     """密码强度校验"""
    #     validate_password(value)
    #     return value

    def update(self, instance, validated_data):
        """自定义更新逻辑"""
        # 提取密码和组信息
        password = validated_data.pop('password', None)
        groups = validated_data.pop('groups', None)

        # 更新基础字段(因为password和groups从validated_data被提取剔除掉了,所以下边这句不会更新password和groups)
        for attr, value in validated_data.items():
            setattr(instance, attr, value)

        # 密码单独处理（加密存储）
        # if password:
        #     instance.set_password(password)

        # 仅当新密码非空且与旧密码不同时更新
        # if password and not instance.check_password(password):
        #     instance.set_password(password)

        # 先保存用户才能操作多对多关系
        instance.save()

        # 更新组关联
        if groups is not None:
            instance.groups.set(groups)

        return instance

    def validate_password(self, value):
        if len(value) < 6:
            raise serializers.ValidationError("密码至少6个字符")
        # if not any(char.isdigit() for char in value):
        #     raise serializers.ValidationError("密码需包含数字")
        return value


# ############## 重置密码管理序列化器:(包括密码验证和短信验证)
class PasswordResetSerializer(serializers.Serializer):
    auth_method = serializers.ChoiceField(choices=['sms', 'newPassword'])
    user_id = serializers.IntegerField()
    phone = serializers.CharField(required=False)
    sms_code = serializers.CharField(required=False)
    new_password = serializers.CharField(required=False)
    confirm_password = serializers.CharField(required=False)
    old_password = serializers.CharField(required=False)

    def validate(self, data):
        auth_method = data.get('auth_method')
        if auth_method == 'sms':
            if not all([data.get('phone'), data.get('sms_code')]):
                raise serializers.ValidationError("短信验证需提供手机号和验证码")
        elif auth_method == 'newPassword':
            if not data.get('old_password'):
                raise serializers.ValidationError("需提供旧密码")
        return data


# ########################## 权限管理序列化器 ##############################
class PermissionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Permission
        fields = ['id', 'name', 'codename', 'content_type']


class GroupSerializer(serializers.ModelSerializer):
    permissions = PermissionSerializer(many=True, read_only=True)
    permission_ids = serializers.ListField(
        child=serializers.IntegerField(),
        write_only=True,
        required=False
    )

    class Meta:
        model = Group
        fields = ['id', 'name', 'permissions', 'permission_ids']

    def update(self, instance, validated_data):
        permission_ids = validated_data.pop('permission_ids', [])
        instance = super().update(instance, validated_data)
        instance.permissions.set(permission_ids)
        return instance


class UserInfoSerializer(serializers.ModelSerializer):
    groups = serializers.PrimaryKeyRelatedField(
        many=True,
        queryset=Group.objects.all(),
        required=False
    )

    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'phone', 'groups', 'is_active']
        extra_kwargs = {
            'password': {'write_only': True}
        }

    def update(self, instance, validated_data):
        groups = validated_data.pop('groups', [])
        instance = super().update(instance, validated_data)
        instance.groups.set(groups)
        return instance


# ########################## 菜单与权限管理序列化器 ##############################
# from .models import Menu, BusinessPermission
#
#
# class MenuSerializer(serializers.ModelSerializer):
#     # 关联权限列表（只读）
#     permissions = serializers.PrimaryKeyRelatedField(
#         many=True,
#         read_only=True,
#         source='permission_set'
#     )
#
#     class Meta:
#         model = Menu
#         fields = [
#             'id',
#             'title',
#             'icon',
#             'weight',
#             'ident',
#             'permissions'
#         ]
#         extra_kwargs = {
#             'ident': {'read_only': True}  # 标识符通常自动生成
#         }
#
#
# class PermissionMenuSerializer(serializers.ModelSerializer):
#     # 显示父权限代码和标题
#     parent_info = serializers.SerializerMethodField()
#
#     # 显示菜单标识符代替ID
#     menu_ident = serializers.SlugRelatedField(
#         source='menu',
#         slug_field='ident',
#         queryset=Menu.objects.all(),
#         required=False,
#         allow_null=True
#     )
#
#     # 递归子权限
#     children = serializers.SerializerMethodField()
#
#     class Meta:
#         model = BusinessPermission
#         fields = [
#             'id',
#             'code',
#             'title',
#             'path',
#             'component',
#             'is_menu',
#             'menu_ident',
#             'parent',
#             'parent_info',
#             'children'
#         ]
#         extra_kwargs = {
#             'parent': {'write_only': True}  # 写操作仍用ID
#         }
#
#     def get_parent_info(self, obj):
#         if obj.parent:
#             return {
#                 'code': obj.parent.code,
#                 'title': obj.parent.title
#             }
#         return None
#
#     def get_children(self, obj):
#         # 递归获取子权限
#         children = obj.permission_set.all()
#         serializer = self.__class__(children, many=True, context=self.context)
#         return serializer.data
#
#     # 重写创建方法处理复杂关系
#     def create(self, validated_data):
#         # 处理菜单标识符转换
#         menu_ident = validated_data.pop('menu_ident', None)
#         if menu_ident:
#             validated_data['menu'] = Menu.objects.get(ident=menu_ident)
#         return super().create(validated_data)
#
#     # 重写更新方法
#     def update(self, instance, validated_data):
#         if 'menu_ident' in validated_data:
#             menu_ident = validated_data.pop('menu_ident')
#             validated_data['menu'] = Menu.objects.get(ident=menu_ident)
#         return super().update(instance, validated_data)
